﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Text;

namespace Vit.Common.Extensions
{
    public static class DictionaryExtension
    {
        public static void AddNotExists<TK, TV>(this IDictionary<TK, TV> dic, TK key, TV val)
        {
            if (dic.ContainsKey(key))
                return;
            dic.Add(key, val);
        }

        public static TK GetKey<TK, TV>(this IDictionary<TK, TV> dic, int index)
        {
            if (index >= 0 && index < dic.Count)
            {
                int i = 0;
                foreach (KeyValuePair<TK, TV> kvp in dic)
                {
                    if (i == index)
                        return kvp.Key;
                    i++;
                }
            }
            return default(TK);
        }

        public static TV GetValue<TK, TV>(this IDictionary<TK, TV> dic, int index)
        {
            if (index >= 0 && index < dic.Count)
            {
                int i = 0;
                foreach (KeyValuePair<TK, TV> kvp in dic)
                {
                    if (i == index)
                        return kvp.Value;
                    i++;
                }
            }
            return default(TV);
        }

        public static void SetValue<TK, TV>(this IDictionary<TK, TV> dic, int index, TV val)
        {
            TK key = dic.GetKey(index);
            if(dic.ContainsKey(key))
                dic[key] = val;
        }

        public static TV GetValue<TK, TV>(this IDictionary<TK, TV> dic, TK key)
        {
            if (dic.ContainsKey(key))
                return dic[key];
            return default(TV);
        }

        public static void Merge<TK, TV>(this IDictionary<TK, TV> dic, IDictionary<TK, TV> dic2)
        {
            if (dic2.Count <= 0)
                return;
            foreach (KeyValuePair<TK, TV> kvp in dic2)
            {
                if (dic.ContainsKey(kvp.Key))
                    dic[kvp.Key] = kvp.Value;
                else
                    dic.Add(kvp.Key, kvp.Value);
            }
        }

        public static List<TV> ToList<TK, TV>(this IDictionary<TK, TV> dic)
        {
            List<TV> list = new List<TV>();
            foreach (KeyValuePair<TK, TV> kvp in dic)
            {
                list.Add(kvp.Value);
            }
            return list;
        }

        public static TV[] ToArray<TK, TV>(this IDictionary<TK, TV> dic)
        {
            TV[] array = new TV[dic.Count];
            int i = 0;
            foreach (KeyValuePair<TK, TV> kvp in dic)
            {
                array[i++] = kvp.Value;
            }
            return array;
        }

        public static TV Find<TK, TV>(this IDictionary<TK, TV> dic, Predicate<TV> predicate)
        {
            if (dic.Count <= 0)
                return default(TV);
            foreach (KeyValuePair<TK, TV> kvp in dic)
            {
                if (predicate(kvp.Value))
                    return kvp.Value;
            }
            return default(TV);
        }

        public static List<TV> FindAll<TK, TV>(this IDictionary<TK, TV> dic, Predicate<TV> predicate)
        {
            if (dic.Count <= 0)
                return null;
            List<TV> list = new List<TV>();
            foreach (KeyValuePair<TK, TV> kvp in dic)
            {
                if (predicate(kvp.Value))
                    list.Add(kvp.Value);
            }
            return list;
        }

        public static void ForEach<TK, TV>(this IDictionary<TK, TV> dic, Func<TV, TV> action)
        {
            TK[] keys = dic.Keys.ToArray();
            foreach (TK key in keys)
            {
                dic[key] = action(dic[key]);
            }
        }

        /// <summary>
        /// 将字符串字典转为字符串
        /// </summary>
        /// <param name="dic">字符串字典</param>
        /// <param name="comma">各字符串之间的分隔符</param>
        /// <param name="equal">字符串名称与值之间的分隔符</param>
        /// <param name="leftComma">值前特殊串</param>
        /// <param name="rightComma">值后特殊串</param>
        /// <returns>字符串</returns>
        public static string ToFormatString(this IDictionary<string, string> dic, string comma, string equal, string leftComma, string rightComma)
        {
            string values = "";
            foreach (KeyValuePair<string, string> kvp in dic)
            {
                values += string.Format("{0}{1}{2}{3}{4}{5}", kvp.Key, equal, leftComma, kvp.Value, rightComma, comma);
            }
            int i = values.LastIndexOf(comma);
            if (i < 0)
                i = values.Length;
            return values.Substring(0, i);
        }

        public static string ToFormatString(this IDictionary<string, string> dic)
        {
            return ToFormatString(dic, ",", "=", "", "");
        }

        public static Dictionary<string, T> Cast<U, T>(this IDictionary<string, U> source, Func<U, T> converter)
        {
            Dictionary<string, T> dic = new Dictionary<string, T>();
            foreach (KeyValuePair<string, U> kvp in source)
            {
                T val = converter(kvp.Value);
                dic.Add(kvp.Key, val);
            }
            return dic;
        }

        public static XElement ToXElement(this IDictionary<string, string> dic, string eleName)
        {
            if (dic == null || dic.Count <= 0)
                return null;

            XElement ele = new XElement(eleName);
            foreach (KeyValuePair<string, string> kvp in dic)
            {
                XElement se = new XElement(kvp.Key);
                se.Value = kvp.Value;
                ele.Add(se);
            }
            return ele;
        }

        public static void RunEach<U, T>(this IDictionary<U, T> dic, Func<KeyValuePair<U, T>, bool> action)
        {
            if (dic == null || dic.Count <= 0)
                return;
            foreach (KeyValuePair<U, T> item in dic)
            {
                bool result = action(item);
                if (result)
                    break;
            }
        }
    }
}
